home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / filesy~1 / mfs609s.zoo / minit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-25  |  14.4 KB  |  633 lines

  1. /* minit Minix INITializer . Freely distributable Minix filesys creator.
  2.  * Copyright S N Henson 1991,1992,1993.
  3.  * Use entirely at your own risk ! If it trashes your hard-drive then
  4.  * it isn't my fault ! 
  5.  */
  6.  
  7. /* Version 0.26 */
  8.  
  9.  
  10. #include <mintbind.h>
  11. #include <stdio.h>
  12. #include <time.h>
  13. #include <string.h>
  14. #include <unistd.h>
  15. #include <stdlib.h>
  16. #include <alloc.h>
  17.  
  18. #include "minixfs/hdio.h"
  19. #include "minixfs/xhdi.h"
  20. #include "minixfs/pun.h"
  21.  
  22. #define MNAME_MAX 14
  23.  
  24. int shift,drive=-1;
  25. long numblocks,numinodes,incr=1;
  26.  
  27. /* various flags */
  28. char protect,sonly,v2,lrecno,tst;
  29.  
  30. struct hdinfo hdinf;
  31.  
  32. unsigned char block_buf[1024];
  33.  
  34. /* Structures we will need */
  35.  
  36. typedef struct  {
  37.   unsigned short  s_ninodes;    /* # usable inodes on the minor device */
  38.   unsigned short  s_nzones;    /* total device size, including bit maps etc */
  39.   unsigned short s_imap_blks;    /* # of blocks used by inode bit map */
  40.   unsigned short s_zmap_blks;    /* # of blocks used by zone bit map */
  41.   unsigned short s_firstdatazn;    /* number of first data zone */
  42.   short int s_log_zsize;    /* log2 of blocks/zone */
  43.   unsigned long s_max_size;    /* maximum file size on this device */
  44.   short s_magic;        /* magic number to recognize super-blocks */
  45.   short pad;            /* padding */
  46.   long s_zones;            /* equivalent to 's_nzones' for V2 */
  47. } super_block;
  48.  
  49.  
  50.  
  51. typedef struct {        /* directory entry */
  52.   unsigned short d_inum;    /* inode number */
  53.   char d_name[MNAME_MAX];        /* character string */
  54. } dir_struct;
  55.  
  56. typedef struct {        /* disk inode. */
  57.   unsigned short i_mode;        /* file type, protection, etc. */
  58.   unsigned short i_uid;            /* user id of the file's owner */
  59.   unsigned long  i_size;        /* current file size in bytes */
  60.   unsigned long  i_mtime;        /* when was file data last changed */
  61.   unsigned char i_gid;            /* group number */
  62.   unsigned char i_nlinks;        /* how many links to this file */
  63.   unsigned short i_zone[9];    /* block nums for direct, ind, and dbl ind */
  64. } d_inode;
  65.  
  66. typedef struct {
  67. unsigned short i_mode;
  68. unsigned short i_nlinks;
  69. unsigned short i_uid;
  70. unsigned short i_gid;
  71. unsigned long i_size;
  72. unsigned long i_atime;
  73. unsigned long i_mtime;
  74. unsigned long i_ctime;
  75. long i_zone[10];
  76. } d_inode2;
  77.  
  78. /* prototypes */
  79.  
  80. #ifdef __STDC__
  81. # define    P(s) s
  82. #else
  83. # define P(s) ()
  84. #endif
  85.  
  86.  
  87. void main P((int argc , char **argv ));
  88. int nrwabs P((int rw , void *buf , unsigned count , long recno , int drive ));
  89. void get_block P((long num ));
  90. void put_block P((long num ));
  91. void check_lrecno P((void ));
  92. void warn P((void ));
  93.  
  94. #undef P
  95.  
  96. void main(argc,argv)
  97. int argc;
  98. char **argv;
  99. {
  100.     extern int optind,opterr;
  101.     extern char *optarg;
  102.     extern int __mint;
  103.     long hderr;
  104.     int c ;
  105.     static char err=0;
  106.     int i,j;
  107.     _BPB *bpb;
  108.     unsigned short ioff,zone1;
  109.         super_block *sblk=(super_block *)block_buf,csblk;
  110.         d_inode *rip=(d_inode *)block_buf;
  111.     d_inode2 *ripn=(d_inode2 *)block_buf;
  112.         dir_struct *dir=(dir_struct *)block_buf;
  113.     unsigned short *srt=(unsigned short *)block_buf;
  114.     long icount, zcount;
  115.  
  116.     struct
  117.     {
  118.         long start;
  119.         long finish;
  120.         char shadow;
  121.         char scsiz;
  122.     } pp;
  123.  
  124.     if(__mint==0)
  125.     {
  126.         fprintf(stderr,"Error: MiNT not active.\n");
  127.         exit(1);
  128.     }
  129.  
  130.     /* Parse command-line options */
  131.     opterr=0;
  132.     while((c=getopt(argc,argv,"b:B:i:I:n:pPSZztV"))!=EOF)
  133.     {
  134.             switch(c){
  135.  
  136.                 case 'B':
  137.             case 'b':
  138.             numblocks=atol(optarg);
  139.             break;
  140.  
  141.             case 'n':
  142.             incr=atol(optarg);
  143.             break;
  144.  
  145.             case 'i':
  146.             case 'I':
  147.             numinodes=atol(optarg);
  148.             break;
  149.  
  150.             case 'P':
  151.             protect=1;
  152.             break;
  153.  
  154.             case 'p':
  155.             protect=2;
  156.             break;
  157.  
  158.             case 'S':
  159.             sonly=1;
  160.             break;
  161.  
  162.             case 'Z':
  163.             protect=1;
  164.             break;    
  165.  
  166.             case 'z':
  167.             protect=2;
  168.             break;
  169.  
  170.             case 'V':
  171.             v2=1;
  172.             break;
  173.  
  174.             case 't':
  175.             tst=1;
  176.             break;
  177.  
  178.             case '?':
  179.             err=1;
  180.             break;
  181.         }
  182.     }
  183.  
  184.     if(argc-optind!=1 || err)
  185.     {
  186.         fprintf(stderr,"Minix-compatible filesystem initializer\n");
  187.         fprintf(stderr,"Copyright S N Henson 1991,1992,1993\n");
  188.         fprintf(stderr,"Version 0.26\n"); 
  189.         fprintf(stderr,"Usage\t(auto)\t: minit drive\n");
  190.         fprintf(stderr,"\t(manual): minit -b blocks -i inodes drive\n");
  191.         fprintf(stderr,"Also :\t-S only write out super-block\n");
  192.         fprintf(stderr,"\t-P/-Z protect filesystem with null disk\n");
  193.         fprintf(stderr,"\t-p/-z make null disk of existing filestystem\n");
  194.         fprintf(stderr,"\t-V make a V2 filesystem\n");
  195.         fprintf(stderr,"\t-n dirincrement\n");
  196.         fprintf(stderr,"\t-t test mode (no writing)\n");
  197.         exit(1);
  198.     }
  199.     drive=(argv[optind][0] & ~32)-'A' ;
  200.  
  201.     bpb=Getbpb(drive);
  202.  
  203.     /* Sanity checking time */
  204.  
  205.     if((incr < 1) || (incr > 16) || ( (incr) & (incr-1) ) )
  206.     {
  207.         fprintf(stderr,"Dirincrement must be a power of two between\n");
  208.         fprintf(stderr,"1 and 16 (inclusive)\n");
  209.         exit(1);
  210.     }
  211.  
  212.     if( (numinodes < 0) || (numinodes > 65535) )
  213.     {
  214.         fprintf(stderr,"Need at least 1 and no more than 65535 inodes\n");
  215.         exit(1);
  216.     }
  217.  
  218.     if(protect==2 && bpb->recsiz!=512)
  219.     {
  220.         fprintf(stderr,"Sorry can't add protection to this filesytem.\n");
  221.         fprintf(stderr,"Sector size not 512 bytes.\n");
  222.         exit(1);
  223.     }
  224.  
  225.     /* Test for physical partition */
  226.     if(!Dcntl(0x109,argv[optind],&pp) && pp.start!=-1) 
  227.     {
  228.         long tstack;
  229.         hdinf.start=pp.start;
  230.         hdinf.size=pp.finish-hdinf.start+1;
  231.         hdinf.scsiz=pp.scsiz;
  232.         hdinf.major = pp.shadow;
  233.         hdinf.drive = drive;
  234.         tstack=Super(0l);
  235.         if(init_icd()==2)
  236.         {
  237.             Super(tstack);
  238.             fprintf(stderr,"Can't kludge ICD bug\n");
  239.             exit(1);
  240.         }
  241.         Super(tstack);
  242.         hdinf.rwmode = RW_PHYS;
  243.         if(hdinf.start > 0xfffe)
  244.         {
  245.             if(no_plrecno(hdinf.major))
  246.             fprintf(stderr,"Cannot access Drive %c:\n",drive+'A');
  247.             hdinf.rwmode |= RW_LRECNO;
  248.         }
  249.     }
  250.     else 
  251.     {
  252.         pp.start=-1;
  253.         if( (hderr=get_hddinf(drive,&hdinf,0)) )
  254.         {
  255.             fprintf(stderr,"Cannot access Drive %c: %s\n",drive+'A',
  256.                                 hdd_err[hderr]);
  257.             exit(1);
  258.         }
  259.     }
  260.     if(tst)
  261.     {
  262.         struct hdinfo hdinf2;
  263.         unsigned int llrecno,xhret,no_phys;
  264.         no_phys=0;
  265.         if(pp.start==-1)
  266.         {
  267.             llrecno=no_lrecno(drive);
  268.             if(llrecno && llrecno!=3)
  269.                 fprintf(stderr,"Logical lrecno error\n");
  270.             else fprintf(stderr,"Logical lrecno OK\n");
  271.         }
  272.         else
  273.         {
  274.             fprintf(stderr,"Physical Partition\n");
  275.             hdinf2=hdinf;
  276.         }
  277.         if( (no_phys=get_hddinf(drive,&hdinf2,1) ) )
  278.     fprintf(stderr,"Can't get physical drive info: %s\n",hdd_err[no_phys]);
  279.         else if( (hdinf2.rwmode & RW_MODE) != RW_XHDI )
  280.         {
  281.             llrecno=no_plrecno(hdinf2.major);
  282.             if(llrecno && llrecno!=3)
  283.                 fprintf(stderr,"Physical lrecno error\n");
  284.             else fprintf(stderr,"Physical lrecno OK\n");
  285.         }
  286.         if( (xhret=XHGetVersion()) ) fprintf(stderr,"XHDI supported"
  287.                    " version %x.%02x\n", xhret>>8,xhret & 0xff);
  288.  
  289.         else fprintf(stderr,"XHDI not supported\n");
  290.         if(!no_phys)
  291.         {
  292.           fprintf(stderr,"Partition start: %ld\n",hdinf2.start);
  293.           if(hdinf2.size)
  294.             fprintf(stderr,"Partition size: %ld\n",hdinf2.size);
  295.           if( (hdinf2.rwmode & RW_MODE) == RW_PHYS)
  296.           {
  297.             unsigned ddev;
  298.             char *sbus;
  299.             ddev=hdinf2.minor;
  300.             fprintf(stderr,"Unit number %d\n",ddev);
  301.             if( ddev & PUN_IDE) sbus="IDE";
  302.             else
  303.             {
  304.                 if( ddev & PUN_SCSI) sbus="SCSI";
  305.                 else sbus="ACSI";
  306.             }
  307.             fprintf(stderr,"%s bus: device %d.(",sbus,
  308.                                    ddev & PUN_UNIT);
  309.             if(ddev & PUN_REMOVABLE) fprintf(stderr,"Removable)\n");
  310.             else fprintf(stderr,"Non-removable)\n");
  311.           }
  312.           else fprintf(stderr,"Major number %d Minor number %d\n",
  313.                              hdinf2.major,hdinf2.minor);
  314.         }
  315.  
  316.     }
  317.  
  318.     if(!numblocks) numblocks=hdinf.size>>hdinf.scsiz;
  319.     else if(hdinf.size && (numblocks > hdinf.size>>hdinf.scsiz))
  320.     {
  321.         fprintf(stderr,"Partition has only %ld blocks\n",
  322.                                hdinf.size>>hdinf.scsiz);
  323.         exit(1);
  324.     }
  325.  
  326.     /* read in boot sector */
  327.     get_block(0);
  328.  
  329.     /* If size of partition not known try BPB/boot sector */
  330.     if(!numblocks)
  331.     {
  332.         if(!bpb || (bpb->recsiz & 511))
  333.         {
  334.             fprintf(stderr,"Can't figure out partition size: "
  335.                              "try the -b option\n");
  336.             exit(1);
  337.         }
  338.  
  339.         numblocks=( (block_buf[19]+( ((long)block_buf[20])<<8))*
  340.                                    bpb->recsiz)>>10;
  341.         if(numblocks < 40 )
  342.         {
  343.                  fprintf(stderr,"%ld blocks ? Is that bootsector OK ?\n",numblocks);
  344.                  exit(1);
  345.         }
  346.     }
  347.  
  348.     if(!v2 && (numblocks > 65535) )
  349.     {
  350.         fprintf(stderr,"V1 filesystems can be at most 65535 blocks\n");
  351.         exit(1);
  352.     }
  353.  
  354.     if(set_lrecno(&hdinf,numblocks))
  355.     {
  356.         fprintf(stderr,"Can't access partition\n");
  357.         exit(1);
  358.     }
  359.  
  360.     if(tst)
  361.     {
  362.         fprintf(stderr,"\nHard disk access information:\nAccess mode: ");
  363.         switch(hdinf.rwmode & RW_MODE)
  364.         {
  365.           case RW_NORMAL:
  366.           fprintf(stderr,"Normal mode\n");
  367.           break;
  368.  
  369.           case RW_XHDI:
  370.           fprintf(stderr,"XHDI mode\n");
  371.           break;
  372.  
  373.           case RW_PHYS:
  374.           fprintf(stderr,"Physical mode\n");
  375.           break;
  376.         }
  377.  
  378.         if(hdinf.rwmode & RW_LRECNO)
  379.                         fprintf(stderr,"Lrecno access\n\n");
  380.         else fprintf(stderr,"Non lrecno access\n\n");
  381.     }
  382.  
  383.     if(numinodes==0)
  384.     {
  385.         numinodes = numblocks/3;
  386.     
  387.         /* Round up inode number to nearest block */
  388.  
  389.         if(v2) numinodes = (numinodes + 15) & ~15;
  390.  
  391.         else numinodes=(numinodes + 31 ) & ~31;
  392.     }
  393.  
  394.     if(numinodes > 65535) numinodes = 65535;
  395.  
  396.     if(protect==2)
  397.     {
  398.         get_block(1);
  399.         if( (sblk->s_magic != 0x137f) && (sblk->s_magic!=0x2468) )
  400.         {
  401.             fprintf(stderr,"Fatal: bad magic number\n");
  402.             exit(1);
  403.         }
  404.     }
  405.  
  406.     if(!tst) warn();
  407.  
  408.     /* OK lets work out some stuff */
  409.  
  410.     if(protect==2) get_block(1);
  411.     else
  412.     {
  413.         bzero(block_buf,1024l);
  414.         /* Super block */
  415.             sblk->s_ninodes=numinodes;
  416.             if(v2) sblk->s_zones=numblocks;
  417.         else sblk->s_nzones=numblocks;
  418.             sblk->s_imap_blks=(numinodes+8192)/8192;
  419.         sblk->s_zmap_blks=(numblocks+8191)/8192;
  420.         sblk->s_firstdatazn=2+sblk->s_imap_blks+sblk->s_zmap_blks
  421.             + ( v2 ? ((numinodes+15)/16) : ((numinodes+31)/32)) ;
  422.         sblk->s_log_zsize=0;
  423.         sblk->s_max_size= v2 ? 0x4041c00l : 0x10081c00l;
  424.         sblk->s_magic= v2 ? 0x2468 : 0x137f;
  425.     }
  426.  
  427.     /* If sector size 512 bytes handle protection now */
  428.     if(protect)
  429.     {
  430.         unsigned pseudo_root,root_entries;
  431.         /* 512 bytes pseudo root after super block */
  432.         if(bpb->recsiz==512)
  433.         {
  434.             bzero(&block_buf[512],512);
  435.             for(i=512;i<1024;i+=32)
  436.             {
  437.                 strncpy(block_buf+i,"MINIXFS    ",11);
  438.                 block_buf[i+11]=0x08;
  439.             }
  440.             put_block(1);
  441.             csblk=*sblk;
  442.             pseudo_root=3;
  443.         }
  444.         else
  445.         /* Not 512 bytes: insert pseudo root after inodes but 
  446.           * before first data zone.
  447.           */
  448.         {
  449.             unsigned secblocks;    /* blocks per log. sector */
  450.              secblocks = bpb->recsiz/1024;
  451.             /* Round up first data zone to sector boundary + 1 */
  452.             sblk->s_firstdatazn += 2*secblocks - 1;
  453.             sblk->s_firstdatazn /= secblocks;
  454.             sblk->s_firstdatazn *= secblocks;
  455.             put_block(1);
  456.             pseudo_root = sblk->s_firstdatazn / secblocks - 1;
  457.             csblk=*sblk;
  458.             /* Pseudo root directory : whole block */
  459.             for(i=0;i<1024;i+=32)
  460.             {
  461.                 strncpy((char *)(block_buf+i),"MINIXFS    ",11);
  462.                 block_buf[i+11]=0x8;
  463.             }
  464.             /* Write them all out */
  465.             for(i = - secblocks ; i < 0 ;i++)
  466.                          put_block(csblk.s_firstdatazn+i);
  467.         }
  468.         /* Set up boot sector to point to pseudo root */
  469.         get_block(0);
  470.         strcpy((char *)(block_buf+2),"MINIX");
  471.         block_buf[16] = 2;    /* 2 FAT's */
  472.         root_entries = bpb->recsiz/32; /* Root directory: 1 sector */
  473.         block_buf[17] = root_entries & 0xff;
  474.         block_buf[18] = root_entries >> 8;
  475.         block_buf[22] = 1;    /* FAT = 1 sector */
  476.         block_buf[23] = 0;
  477.         pseudo_root-=2;
  478.         block_buf[14] = pseudo_root & 0xff;
  479.         block_buf[15] = pseudo_root >> 8;
  480.         put_block(0);
  481.     }
  482.     else
  483.     {
  484.         put_block(1);
  485.         csblk=*sblk;
  486.     }
  487.  
  488.     if( sonly || protect==2 ) exit(0);
  489.  
  490.     ioff=2+csblk.s_imap_blks+csblk.s_zmap_blks;
  491.     zone1=csblk.s_firstdatazn;
  492.  
  493.     bzero(block_buf,1024l);
  494.  
  495.     /* Inode bitmaps */
  496.  
  497.     icount = numinodes + 1;
  498.     for(i=2;i<2+csblk.s_imap_blks;i++)
  499.     {
  500.         if(i==2)
  501.         {
  502.             srt[0]=3;
  503.         }
  504.         if(icount < 8192) /* Need to mark dead inodes as used */
  505.         {
  506.             if(icount & 15)
  507.             {
  508.                 srt[icount/16] = 0xffff << (icount & 15);
  509.                 icount+= 16 - (icount & 15);
  510.             }
  511.             for(j=icount/16;j<512;j++)srt[j]=0xffff;
  512.         }
  513.         put_block(i);
  514.         if(i==2)srt[0]=0;
  515.         icount-=8192;
  516.     }
  517.  
  518.     bzero(block_buf,1024l);
  519.  
  520.         /* Zone bitmaps */
  521.  
  522.     zcount = numblocks + 1 - csblk.s_firstdatazn;
  523.     for(i=2+csblk.s_imap_blks;i<ioff;i++)
  524.     {
  525.         if(i==2+csblk.s_imap_blks)
  526.         {
  527.             srt[0]=3;
  528.         }
  529.         if (zcount < 8192) /* Need to mark dead zones as used */
  530.         {
  531.             if(zcount < 0) zcount=0;
  532.             if(zcount & 15)
  533.             {
  534.                 srt[zcount/16] = 0xffff << (zcount & 15);
  535.                 zcount+= 16 - (zcount & 15);
  536.             }
  537.             for(j=zcount/16;j<512;j++)srt[j]=0xffff;
  538.         }
  539.         put_block(i);
  540.         if(i==2+csblk.s_imap_blks)srt[0]=0;
  541.         zcount-=8192;
  542.     }
  543.  
  544.     bzero(block_buf,1024l);
  545.  
  546.     /* Initialise inodes */
  547.     
  548.     for(i=ioff;i<ioff+
  549.             (v2 ? ((numinodes +15)/16) : ((numinodes+31)/32 )) ;i++)
  550.     {
  551.         if(i==ioff) /* Root inode , initialise it properly */
  552.         {
  553.             if(v2)
  554.             {
  555.                 ripn->i_mode=040777; /* Directory */
  556.                 ripn->i_size=32*incr;
  557.                 ripn->i_mtime=time((time_t *)0);
  558.                 ripn->i_ctime=ripn->i_mtime;
  559.                 ripn->i_atime=ripn->i_mtime;
  560.                 ripn->i_nlinks=2;
  561.                 ripn->i_zone[0]=zone1;
  562.             }
  563.             else
  564.             {
  565.                 rip->i_mode=040777; /* Directory */
  566.                 rip->i_size=32*incr;
  567.                 rip->i_mtime=time((time_t *)0);
  568.                 rip->i_nlinks=2;
  569.                 rip->i_zone[0]=zone1;
  570.             }
  571.         }    
  572.         put_block(i);
  573.         if(i==ioff)bzero(block_buf,1024l);
  574.     }
  575.  
  576.     bzero(block_buf,1024l);
  577.     /* And finally the root directory */
  578.     dir[0].d_inum=1;
  579.     strcpy(dir[0].d_name,".");
  580.     dir[incr].d_inum=1;
  581.     strcpy(dir[incr].d_name,"..");
  582.     put_block(zone1);
  583.     if(!tst) fprintf(stderr,"Initialised OK.\n");
  584.     fprintf(stderr,"%ld Blocks, %ld Inodes.\n",numblocks,numinodes);
  585.  
  586.     /* Force media change on specified drive */
  587.     if(Dlock(1,drive)) 
  588.         fprintf(stderr,"Can't Lock Drive, Reboot to be sure\n");
  589.  
  590.     exit(0);
  591. }
  592.  
  593. void get_block(num)
  594. long num;
  595. {
  596.     long r;
  597.  
  598.     if( (r = block_rwabs(2,block_buf,1,num,&hdinf)) )
  599.     {
  600.         fprintf(stderr,"Fatal Read Error %ld block %ld\n",r,num);
  601.         exit(2);
  602.     }
  603. }
  604.  
  605. void put_block(num)
  606. long num;
  607. {
  608.     long r;
  609.  
  610.     if(tst) return;
  611.  
  612.     if( (r = block_rwabs(3,block_buf,1,num,&hdinf)) )
  613.     {
  614.         fprintf(stderr,"Fatal Write Error %ld block %ld\n",r,num);
  615.         exit(2);
  616.     }
  617. }
  618.  
  619. void warn()
  620. {
  621.     int ch;
  622.     fprintf(stderr,"WARNING ! THIS %s TOTALLY DESTROY ANY DATA ON ",
  623.                   (sonly || protect==2 ) ? "MAY":"WILL");
  624.     fprintf(stderr,"DRIVE %c !\n",drive+'A');
  625.     fprintf(stderr,"Are you ABSOLUTELY SURE you want to do this (y/n)?\n");
  626.     ch=Crawcin() & 0xff ;
  627.     if(ch!='Y' && ch!='y')
  628.     {
  629.         fprintf(stderr,"Aborted\n");
  630.         exit(0);
  631.     }
  632. }
  633.